using System;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Windows.Forms;

namespace ChromiumUpdater
{
    public partial class FrmMain : IconForm
    {
        private bool _normalCheckIntervalSet;

        MySettings _my = new MySettings();
        readonly Chrome _chrome = new Chrome();

        #region Form
        public FrmMain()
        {
            InitializeComponent();
        }

        private void DownloadCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // enable check again
            timerCheck.Enabled = true;
            btnCheck.Enabled = true;

            // unzip file
            var lastMessage = tsslblLastCheckTime.Text;
            try
            {
                _chrome.Unzipp();
            }
            catch (Exception ex)
            {
                toolStripStatusLabel1.Text = "Current version: " + _my.CurrentBuild;
                tsslblLastCheckTime.Text = lastMessage;
                throw ex;
            }

            // replace current build
            if (_chrome.CheckChromeRunning()) // chrome still running
            {                
                var d = ShowRetry(); // let user close chorme                
                if (d == DialogResult.Cancel)
                {
                    toolStripStatusLabel1.Text = "User cancelled";
                    return;
                }

                System.Threading.Thread.Sleep(15*1000); // wait for 15 s for user action and chrome shutting down
            }

            toolStripStatusLabel1.Text = "Copying file...";
            _chrome.Copy();

            toolStripStatusLabel1.Text = "Starting Chrome...";

            // Start chromium
            if (_my.StartAfterUpdating)
            {
                _chrome.Start();

                prgDownload.Value = 0;
                lblProgress.Text = "Awaiting Download";
            }
            _chrome.CurrentBuild = _chrome.LatestBuild;
            _my.CurrentBuild = _chrome.CurrentBuild;
            MySettings.Save(_my);

            toolStripStatusLabel1.Text = "Current version: " + _my.CurrentBuild;
            tsslblLastCheckTime.Text =
                "Last Check Time: " + DateTime.Now.ToLongTimeString() + "(current version)";

            // clean up olde builds
            var c = new Common();
            var builds = c.GetBuildDirs().Skip(10);
            foreach (var b in builds)
            {
                Directory.Delete(b.FullName, true);
            }
        }

        private void DownloadingProgreeChanged(object sender, ProgressChangedEventArgs e)
        {
            // Make progress on the progress bar
            prgDownload.Value = e.ProgressPercentage;

            // Display the current progress on the form
            lblProgress.Text = "Downloaded " + e.ProgressPercentage + " %";
        }

        private void CheckCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            toolStripStatusLabel1.Text = "Current version: " + _chrome.CurrentBuild;
            var cr = (CheckResult)e.Result;
            _chrome.LatestBuild = cr.Rev;

            // build not be built out yet
            if (_chrome.LatestBuild == -1)
            {
                tsslblLastCheckTime.Text =
                     "Last check time: " + DateTime.Now.ToLongTimeString() + "(no new version)";

                return;
            }

            // no new build found 
            if (_chrome.LatestBuild == _chrome.CurrentBuild)
            {
                //SetLastCheckTime();
                tsslblLastCheckTime.Text =
                    "Last check time: " + DateTime.Now.ToLongTimeString() + "(no new version)";

            }
                // latestBuild > currentBuild,but same with last check result, not alert again
            else if (_chrome.LatestBuild == _chrome.LastCheckBuild)
            {
                tsslblLastCheckTime.Text =
                    "Last Check Time: " + DateTime.Now.ToLongTimeString() + "(new version: " + _chrome.LatestBuild + ")";
                btnUpdate.Enabled = true;
            }
                // latestBuild > lastCheckBuild
            else
            {
                notifyIcon1.ShowBalloonTip(
                    15,
                    "Hi, dude",
                    "new build " + _chrome.LatestBuild +
                    Environment.NewLine + Environment.NewLine +
                    cr.Log,
                    ToolTipIcon.Info);
                tsslblLastCheckTime.Text =
                    "Last Check Time: " +
                    DateTime.Now.ToLongTimeString() +
                    "(new version: " + _chrome.LatestBuild + ")";

                btnUpdate.Enabled = true;
            }

            btnCheck.Enabled = true;
            timerCheck.Enabled = true;
        }

        private void formDownload_Load(object sender, EventArgs e)
        {
            // fire check immediately after from load, will set normal check interval in next tick
            timerCheck.Interval = 1000;
            timerCheck.Enabled = true;
            btnCheck.Enabled = false;
            _my = MySettings.Load();

            toolStripStatusLabel1.Text = "You are using build:" + _chrome.CurrentBuild;
        }

        private void formDownload_Resize(object sender, EventArgs e)
        {
            if (WindowState == FormWindowState.Minimized)
            {
                ShowInTaskbar = false;
            }
            else if (WindowState == FormWindowState.Normal)
            {
                ShowInTaskbar = true;
            }
        }

        private void formDownload_FormClosing(object sender, FormClosingEventArgs e)
        {
            WindowState = FormWindowState.Minimized;
            e.Cancel = true;
        }
        #endregion

        #region Button
        private void btnUpdate_Click(object sender, EventArgs e)
        {
            toolStripStatusLabel1.Text = "Downloading latest build " + _chrome.LatestBuild;

            btnUpdate.Enabled = false;

            //disable check
            timerCheck.Enabled = false;
            btnCheck.Enabled = false;

            lblProgress.Text = "Download Starting";
            _chrome.DownloadCompleted = DownloadCompleted;
            _chrome.DownloadProgressChanged = DownloadingProgreeChanged;
            _chrome.DownloadBuild();
        }

        private void btnLaunch_Click(object sender, EventArgs e)
        {
            _chrome.Start();
        }

        private void btnCheck_Click(object sender, EventArgs e)
        {
            btnCheck.Enabled = false;
            timerCheck.Enabled = false;

            _chrome.CheckBuildCompleted = CheckCompleted;
            toolStripStatusLabel1.Text = "Checking new build...";
            _chrome.CheckNewBuild();
        }

        #endregion

        #region Menu
        private void notifyIcon1_BalloonTipClicked(object sender, EventArgs e)
        {
            WindowState = FormWindowState.Normal;
        }

        private void CloseToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CloseApp();
        }

        private void notifyIcon1_DoubleClick(object sender, EventArgs e)
        {
            if (WindowState == FormWindowState.Normal)
            {
                WindowState = FormWindowState.Minimized;
                ShowInTaskbar = false;
            }
            else if (WindowState == FormWindowState.Minimized)
            {
                WindowState = FormWindowState.Normal;
                ShowInTaskbar = true;
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CloseApp();
        }

        private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var frmSetting = new FrmSettings();
            var dr = frmSetting.ShowDialog();

            // reload settings after changing
            if (DialogResult.OK == dr)
            {
                _my = MySettings.Load();
                timerCheck.Interval = _my.CheckInterval * 1000 * 60;
            }
        }

        private void RevertToLastReversionToolStripMenuItemClick(object sender, EventArgs e)
        {
            // replace current build
            var f = new FrmRevert();
            var dr = f.ShowDialog();
            if (dr == DialogResult.OK)
            {
                while (_chrome.CheckChromeRunning())
                {
                    var d = ShowRetry();
                    if (d == DialogResult.Cancel)
                    {
                        toolStripStatusLabel1.Text = "User cancelled";
                        return;
                    }
                }
                _chrome.Revert(f.SelectedBuild);
                toolStripStatusLabel1.Text = "Restore to version " + f.SelectedBuild;
                _chrome.Start();
            }
        }

        private void aboutToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            var fa = new FrmAbout {ShowInTaskbar = false, ShowIcon = false};
            fa.ShowDialog();
        }

        #endregion

        private void timerCheck_Tick(object sender, EventArgs e)
        {
            btnCheck.Enabled = false;
            _chrome.CheckBuildCompleted = CheckCompleted;
            toolStripStatusLabel1.Text = "Checking new build...";
            _chrome.CheckNewBuild();

            // set normal check interval
            if (!_normalCheckIntervalSet)
            {
                timerCheck.Interval = _my.CheckInterval * 1000 * 60;
                _normalCheckIntervalSet = true;
            }
        }

        #region Help Method

        private DialogResult ShowRetry()
        {
            toolStripStatusLabel1.Text = "Close chrome to update";
            return MessageBox.Show("Please Close Chrome to continue", "error", MessageBoxButtons.RetryCancel);
        }

        private void CloseApp()
        {
            notifyIcon1.Visible = false;
            notifyIcon1.Dispose();
            Dispose();
        }
        #endregion
    }
}